package com.example.cloud.config.eureka;

import java.util.List;
import java.util.Set;

import org.springframework.cloud.client.discovery.DiscoveryClient;

import com.example.cloud.config.GrpcChannelFactory;
import com.example.cloud.config.interceptor.GlobalClientInterceptorRegistry;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import io.grpc.Channel;
import io.grpc.ClientInterceptor;
import io.grpc.ClientInterceptors;
import io.grpc.LoadBalancer;
import io.grpc.LoadBalancer.Factory;
import io.grpc.netty.NettyChannelBuilder;

/**
 * 基于Eureka的Channel Factory
 * 
 * @author tongyufu
 *
 */
public class DiscoveryClientChannelFactory implements GrpcChannelFactory {

    private DiscoveryClient discoveryClient;
    private LoadBalancer.Factory loadBalancerFactory;
    private final GlobalClientInterceptorRegistry globalClientInterceptorRegistry;

    public DiscoveryClientChannelFactory(DiscoveryClient discoveryClient,
                                         Factory loadBalancerFactory,
                                         GlobalClientInterceptorRegistry globalClientInterceptorRegistry) {
        this.discoveryClient = discoveryClient;
        this.loadBalancerFactory = loadBalancerFactory;
        this.globalClientInterceptorRegistry = globalClientInterceptorRegistry;
    }

    @Override
    public Channel createChannel(String name) {
        return this.createChannel(name, null);
    }

    @Override
    public Channel createChannel(String name, List<ClientInterceptor> interceptors) {
        NettyChannelBuilder builder = NettyChannelBuilder.forTarget(name);
        builder.loadBalancerFactory(loadBalancerFactory);
        builder.nameResolverFactory(new DiscoveryClientResolverFactory(discoveryClient));
        builder.usePlaintext(true);
        Channel channel = builder.build();

        List<ClientInterceptor> globalInterceptorList = globalClientInterceptorRegistry
            .getClientInterceptors();
        Set<ClientInterceptor> interceptorSet = Sets.newHashSet();
        if (globalInterceptorList != null && !globalInterceptorList.isEmpty()) {
            interceptorSet.addAll(globalInterceptorList);
        }
        if (interceptors != null && !interceptors.isEmpty()) {
            interceptorSet.addAll(interceptors);
        }
        return ClientInterceptors.intercept(channel, Lists.newArrayList(interceptorSet));
    }

}
